﻿
using System;
using System.Drawing;

namespace GECS.Util {

	/// <summary>
	/// This class can be used to convert images. Note that all the methods of this
	/// class are declared as static. Supports the following image operations.
	/// <list>
	/// <item>Split images</item>
	/// <item>Resize image</item>
	/// <item>Create tiled image</item>
	/// <item>Create empty transparent image</item>
	/// <item>Create a colored image</item>
	/// <item>Flip image horizontally</item>
	/// <item>Flip image vertically</item>
	/// <item>Clone image</item>
	/// <item>Rotate image</item>
	/// </list>
	/// </summary>
    public class ImageTool {

		/// <summary>
		/// Splits an image into a number of rows and columns
		/// </summary>
		/// <param name="img">The image to be split</param>
		/// <param name="rows">The number of rows</param>
		/// <param name="cols">The number of columns</param>
		/// <returns>The array of split images in the vertical order</returns>
        public static Image[] SplitImage(Image img, int rows, int cols) {
            int w = img.Width / cols;
            int h = img.Height / rows;
            int num = rows * cols;
            int count = 0;
            Image[] imgs = new Image[num];
            for (int x=0; x<rows; x++) {
                for (int y=0; y<cols; y++) {
                    Bitmap bmp = new Bitmap(w, h);
                    Graphics g = Graphics.FromImage((Image)bmp);
                    g.DrawImage(img, 0, 0, new Rectangle(w*y, h*x, w, h), GraphicsUnit.Pixel);
                    g.Dispose();
                    imgs[count] = (Image)bmp;
                    count++;
                }
            }
            return imgs;
        }

		/// <summary>
		/// Resizes a given image to given width and height
		/// </summary>
		/// <param name="img">The image to be resized</param>
		/// <param name="width">The new width</param>
		/// <param name="height">The new height</param>
		/// <returns>The resized image</returns>
        public static Image Resize(Image img, int width, int height) {
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage((Image)bmp);
            g.DrawImage(img, 0, 0, width, height);
            g.Dispose();
            return (Image)bmp;
        }

		/// <summary>
		/// Creates a tiled image with an image upto given width and height
		/// </summary>
		/// <param name="img">The source image</param>
		/// <param name="width">The width of image to be created</param>
		/// <param name="height">The height of the image to be created</param>
		/// <returns>The created image</returns>
        public static Image CreateTiledImage(Image img, int width, int height) {
            Bitmap bmp = new Bitmap(width, height);
            int imgW = img.Width;
            int imgH = img.Height;
            int numX = (width/imgW) + 2;
            int numY = (height/imgH) + 2;
            Graphics g = Graphics.FromImage((Image)bmp);
            for (int y=0; y<numY; y++) {
                for (int x=0; x<numX; x++) {
                    g.DrawImage(img, x*imgW, y*imgH, imgW, imgH);
                }
            }
            g.Dispose();
            return (Image)bmp;
        }

		/// <summary>
		/// Creates an empty image with transparency
		/// </summary>
		/// <param name="width">The width of required image</param>
		/// <param name="height">The height of required image</param>
		/// <returns>The created image</returns>
        public static Image GetEmptyImage(int width, int height) {
            return (Image)new Bitmap(width, height);
        }

		/// <summary>
		/// Creates a colored image with a specified color
		/// </summary>
		/// <param name="c">The color to be filled with</param>
		/// <param name="width">The width of the required image</param>
		/// <param name="height">The height of the required image</param>
		/// <returns>The created image</returns>
        public static Image GetColoredImage(Color c, int width, int height) {
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage((Image)bmp);
            g.FillRectangle(new SolidBrush(c), 0, 0, width, height);
            g.Dispose();
            return (Image)bmp;
        }

		/// <summary>
		/// Flips an image horizontally. (Mirrors it)
		/// </summary>
		/// <param name="img">The source image</param>
		/// <returns>The image after flip</returns>
        public static Image FlipImageHorizontally(Image img) {
            Image i = Clone(img);
            i.RotateFlip(RotateFlipType.RotateNoneFlipX);
            return i;
        }

		/// <summary>
		/// Flips an image vertically. (Mirrors it)
		/// </summary>
		/// <param name="img">The source image</param>
		/// <returns>The image after flip</returns>
        public static Image FlipImageVertically(Image img) {
            Image i = Clone(img);
            i.RotateFlip(RotateFlipType.RotateNoneFlipY);
            return i;
        }

		/// <summary>
		/// Clones an image. After cloning, a copy of the image is returned.
		/// </summary>
		/// <param name="img">The image to be cloned</param>
		/// <returns>The clone of the given image</returns>
        public static Image Clone(Image img) {
            Bitmap bmp = new Bitmap(img.Width, img.Height);
            Graphics.FromImage((Image)bmp).DrawImage(img, 0, 0);
            return (Image)bmp;
        }

		/// <summary>
		/// Rotates an image. Actually rotates a new copy of the image.
		/// </summary>
		/// <param name="img">The image to be rotated</param>
		/// <param name="angle">The angle in degrees</param>
		/// <returns>The rotated image</returns>
        public static Image Rotate(Image img, float angle) {
            Bitmap newBitmap = new Bitmap(img.Width, img.Height);
            Graphics graphics = Graphics.FromImage(newBitmap);
            newBitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
            graphics.TranslateTransform((float)img.Width / 2, (float)img.Height / 2);
            graphics.RotateTransform(angle);
            graphics.TranslateTransform(-(float)img.Width / 2, -(float)img.Height / 2);
            graphics.DrawImage(img, 0, 0);
            return newBitmap;
        }
		
		/// <summary>
		/// Makes a color in an Image transparent.
		/// </summary>
		public static Image Mask(Image img, Color c){
			Bitmap bmp = (Bitmap)Clone(img);
			for (int x=0; x<bmp.Width; x++){
				for (int y=0; y<bmp.Height; y++){
					Color p = bmp.GetPixel(x, y);
					if (p.ToArgb()==c.ToArgb()){
						Color nc = Color.FromArgb(0, p.R, p.G, p.B);
						bmp.SetPixel(x, y, nc);
					}
				}
			}
			return (Image)bmp;
		}

    }

}
